package com.gearbox.core.driver.impl;

import com.gearbox.core.configuration.MetricConfiguration;
import com.gearbox.core.driver.CesHandler;
import com.gearbox.core.http.HttpConfigFactory;
import com.gearbox.core.metric.Metric;
import com.gearbox.core.util.SdkResponseAssertion;
import com.huaweicloud.sdk.ces.v1.CesClient;
import com.huaweicloud.sdk.ces.v1.model.CreateMetricDataRequest;
import com.huaweicloud.sdk.ces.v1.model.CreateMetricDataResponse;
import com.huaweicloud.sdk.ces.v1.model.MetricDataItem;
import com.huaweicloud.sdk.ces.v1.model.MetricInfo;
import com.huaweicloud.sdk.ces.v1.model.MetricsDimension;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;

import javax.annotation.PostConstruct;

@Component
public class CesHandlerImpl implements CesHandler {
    private static final Logger LOG = LoggerFactory.getLogger(CesHandlerImpl.class);

    private final MetricConfiguration metricConfiguration;

    private final HttpConfigFactory configFactory;

    private CesClient cesClient;

    public CesHandlerImpl(MetricConfiguration envConfig, HttpConfigFactory configFactory) {
        this.metricConfiguration = envConfig;
        this.configFactory = configFactory;
    }

    @PostConstruct
    public void init() {
        initCesClient();
    }

    private void initCesClient() {
        cesClient = CesClient.newBuilder()
            .withHttpConfig(configFactory.getHttpConfig())
            .withCredential(configFactory.getBasicCredentials())
            .withEndpoint(metricConfiguration.getMetricReportEndpoint())
            .build();
    }

    @Override
    public void reportMetric(Metric metric) {
        CreateMetricDataRequest request = buildCreateMetricDataRequest(metric);
        LOG.info("report CES metric begin, request={}", request);
        CreateMetricDataResponse response = cesClient.createMetricData(request);
        LOG.info("report CES metric end, resp={}", response);
        SdkResponseAssertion.assertError(response, "report metric failed");
    }

    private CreateMetricDataRequest buildCreateMetricDataRequest(Metric metric) {
        return new CreateMetricDataRequest().withBody(buildMetricDataItems(metric));
    }

    private List<MetricDataItem> buildMetricDataItems(Metric metric) {
        return Collections.singletonList(
            new MetricDataItem()
                .withMetric(buildMetricInfo(metric))
                .withTtl(metricConfiguration.getReportTtl())
                .withCollectTime(System.currentTimeMillis())
                .withValue(metric.getValue().doubleValue())
                .withType("int"));
    }

    private MetricInfo buildMetricInfo(Metric metric) {
        return new MetricInfo()
            .withMetricName(metric.getName())
            .withNamespace(metricConfiguration.getNamespace())
            .withDimensions(buildMetricsDimensions());

    }

    private List<MetricsDimension> buildMetricsDimensions() {
        return Collections.singletonList(
            new MetricsDimension()
                .withName(metricConfiguration.getDimensionName())
                .withValue(metricConfiguration.getDimensionId()));
    }
}
